/*
 * This file is part of the JNR project.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.liuyun.unixsocket;

import jnr.enxio.channels.NativeSelectorProvider;
import jnr.unixsocket.UnixServerSocketChannel;
import jnr.unixsocket.UnixSocketAddress;

import java.io.IOException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Iterator;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @author liuyun
 */
public class UnixServer {
    private static final Logger LOGGER = Logger.getLogger(UnixServer.class.getName());
    public static final String SOCK_FILE = "/tmp/test.sock";

    public static void main(String[] args) {
        LOGGER.info("启动server...");
        java.io.File path = new java.io.File(SOCK_FILE);
        path.deleteOnExit();
        UnixSocketAddress address = new UnixSocketAddress(path);
        try (UnixServerSocketChannel channel = UnixServerSocketChannel.open();
             Selector sel = NativeSelectorProvider.getInstance().openSelector()) {
            channel.configureBlocking(false);
            channel.socket().bind(address);
            channel.register(sel, SelectionKey.OP_ACCEPT, new ServerActor(channel, sel));

            while (sel.select() > 0) {
                Set<SelectionKey> keys = sel.selectedKeys();
                Iterator<SelectionKey> iterator = keys.iterator();
                boolean running = false;
                boolean cancelled = false;
                while (iterator.hasNext()) {
                    SelectionKey k = iterator.next();
                    Actor a = (Actor) k.attachment();
                    if (a.hasReady()) {
                        running = true;
                    } else {
                        k.cancel();
                        cancelled = true;
                    }
                    iterator.remove();
                }
                if (!running && cancelled) {
                    LOGGER.info("No Actors Running any more");
                    break;
                }
            }
        } catch (IOException ex) {
            LOGGER.log(Level.SEVERE, null, ex);
        }
        LOGGER.info("UnixServer EXIT");
    }

}
